<template>
  <div class="dailog-container">
    <div class="tree-box vxe-table--ignore-clear">
      <div class="tree-filter">
        <el-form
          class="filter-input"
          :show-feedback="false"
          @submit.prevent="handleSearch"
        >
          <el-form-item>
            <el-input
              v-model="filterText"
              clearable
              placeholder="请输入名称筛选"
              maxlength="10"
              @clear="handleSearch"
            >
              <template #append>
                <el-button attr-type="submit" @click="handleSearch">
                  <template #icon> sea </template>
                </el-button>
              </template>
            </el-input>
          </el-form-item>
        </el-form>
        <div v-show="!isSearching" class="filter-tree">
          <vxe-table
            border="none"
            :data="props.options"
            :row-config="{
              isCurrent: false,
              isHover: true,
              keyField: 'key'
            }"
            :virtual-y-config="{ enabled: false }"
            :show-header="false"
            :tree-config="{
              expandAll: true,
              transform: false
            }"
          >
            <vxe-column tree-node>
              <template #default="{ row }">
                <div class="custom-checkbox">
                  <template v-if="row.type == type">
                    <VxeCheckbox
                      :model-value="isCheckedRow(row)"
                      :disabled="row.disabled"
                      @change="() => handleRowCheck(row)"
                    >
                      <span :class="{ activeColor: row.isChecked }">
                        <el-icon v-if="row.type == 2">
                          <!-- <Person /> -->
                          p2
                        </el-icon>
                        {{ row.name }}
                      </span>
                    </VxeCheckbox>
                  </template>
                  <template v-else>
                    <svg-icon name="department"></svg-icon>
                    {{ row.name }}
                  </template>
                </div>
              </template>
            </vxe-column>
          </vxe-table>
        </div>

        <div v-show="isSearching" class="filter-tree">
          <search-pane
            ref="searchPaneRef"
            v-model="valueBak"
            :type="type"
            :options="options"
            :multiple="multiple"
          ></search-pane>
        </div>
      </div>

      <div class="tree-container">
        <div class="container-header">
          <div>已选：{{ selectedDatas.length }}</div>
          <el-button link type="danger" @click="clear">清空</el-button>
        </div>
        <div ref="listContainer" class="container-body">
          <div
            v-for="(tag, idx) in selectedDatas"
            :key="tag.key"
            class="org"
            :class="{ border: multiple }"
          >
            <div v-if="multiple" class="sort-handle">
              <el-icon size="20"><SwapVertical /></el-icon>
            </div>
            <div class="left">
              <span class="name">{{ tag.name }}</span>
              <template v-if="tag.type == 2">
                <div
                  v-for="des in tag.deptInfo"
                  :key="des.id"
                  class="dept-name"
                >
                  {{ fmtDept(des) }}
                </div>
              </template>
            </div>
            <div class="right">
              <el-icon class="btn" @click="handleRemove(idx)">
                <!-- <Close /> -->
                close
              </el-icon>
            </div>
          </div>
        </div>
      </div>

      <div v-if="loading" class="loading-container"> lodaing.... </div>
    </div>

    <div class="dialog-footer">
      <el-button @click="$emit('close')">取消</el-button>
      <el-button type="primary" @click="submit"> 确认 </el-button>
    </div>
  </div>
</template>

<script lang="ts" setup name="SelectPane">
  import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue';
  import {
    type SSModelValue,
    TreeSelectDailogProps,
    type TData
  } from '../props';
  import SearchPane from './searchPane.vue';
  import Sortable from 'sortablejs';
  import { flatTreeData, genUserDeptsData } from '../utils';
  import { cloneDeep } from 'lodash';

  type SearchPlanInstance = {
    clear(): void;
    search(val?: string): Promise<void>;
  };

  const props = defineProps(TreeSelectDailogProps);

  const emit = defineEmits(['change', 'submit', 'close', 'refresh']);

  const filterText = ref<string>('');

  const isSearching = ref(false);

  const searchPaneRef = ref<SearchPlanInstance>();

  const valueBak = ref<SSModelValue>();

  const listContainer = ref<any>();

  const sortIns = ref<Sortable>();

  const flatOptions = computed(() => {
    if (props.options == undefined) return [];
    if (props.type === 1) return flatTreeData(props.options);
    return genUserDeptsData(props.options);
  });

  const selectedDatas = computed<any[]>(() => {
    if (!valueBak.value) return [];
    if (Array.isArray(valueBak.value)) {
      return valueBak.value.map((item) =>
        flatOptions.value.find((option: TData) => option.id === item.id)
      );
    }
    return [
      flatOptions.value.find(
        (option: TData) => option.id === (valueBak.value as TData)?.id
      )
    ];
  });

  const handleSearch = () => {
    isSearching.value = !!filterText.value.trim();
    if (filterText.value.trim()) {
      searchPaneRef.value?.search(filterText.value);
    }
  };

  const clear = () => {
    valueBak.value = undefined;
  };

  // 取消选中
  const handleRemove = (idx: number) => {
    const selection = [...selectedDatas.value];
    if (Array.isArray(valueBak.value)) {
      selection.splice(idx, 1);
      valueBak.value = selection;
    } else {
      valueBak.value = undefined;
    }
  };

  const submit = () => {
    emit('change', valueBak.value);
  };

  const handleRowCheck = (row: any) => {
    if (row.disabled) return;
    return props.multiple ? handleDiyCheckbox(row) : handleDiyRadio(row);
  };

  const handleDiyCheckbox = async (row: any) => {
    if (!valueBak.value) {
      const selected = flatOptions.value.find(
        (item: TData) => item.id === row.id
      );
      if (selected) {
        valueBak.value = [selected];
      }
    } else {
      const index = valueBak.value.findIndex(
        (item: TData) => item.id === row.id
      );
      if (index > -1) {
        valueBak.value.splice(index, 1);
      } else {
        const ele = flatOptions.value.find((item: TData) => item.id === row.id);
        valueBak.value.push(ele);
      }
    }
  };

  const handleDiyRadio = (row: any) => {
    const selected = flatOptions.value.find(
      (item: TData) => item.id === row.id
    );
    valueBak.value = selected;
  };

  const isCheckedRow = (row: TData) => {
    if (props.multiple) {
      return !!valueBak.value?.find((item: TData) => {
        return item.id == row.id && item.type == row.type;
      });
    } else {
      if (!valueBak.value) return false;
      return (
        (valueBak.value as TData).id == row.id &&
        (valueBak.value as TData).type == row.type
      );
    }
  };

  const fmtDept = (depts: []) => depts.map((item: any) => item.name).join('/');

  onMounted(() => {
    valueBak.value = cloneDeep(props.modelValue);
    nextTick(() => {
      if (!listContainer.value) return;
      sortIns.value = new Sortable(listContainer.value as HTMLElement, {
        animation: 150,
        handle: '.sort-handle',
        removeCloneOnHide: true,
        onEnd: (evt) => {
          const { oldIndex = 0, newIndex = 0 } = evt;
          if (oldIndex == newIndex) return;
          const selection = [...selectedDatas.value];
          const [removed] = selection.splice(oldIndex, 1);
          selection.splice(newIndex, 0, removed);
          valueBak.value = selection;
        }
      });
    });
  });

  onBeforeUnmount(() => {
    if (sortIns.value) {
      sortIns.value.destroy();
    }
  });
</script>

<style scoped>
  @import './index.less';
</style>
